昨天已經成功地將firebase裡的dynamic data儲存至indexedDB了,接下來因為我目前使用的cache strategies是「cache then network」,一開始是會先到cache或是indexedDB來獲取資源的。
所以讓我們來看一下要如何在feed.js裡來讀取indexedDB內的資料
首先,我會在utility.js中,新增一個function:(流程基本上與寫入相同,只是最後是呼叫getAll() method)
function readAllData(objectStore) {
return dbPromise.then(function(db) {
var tx = db.transaction(objectStore, 'readonly');
var store = tx.objectStore(objectStore);
return store.getAll();
});
}
接下來要注意的是,為了在feed.js也要能使用indexedDB第三方套件和我所寫的utility.js,記得要在index.html中導入。
這裡要開始修改在feed.js中的cache then network strategies的程式碼:
var url = 'https://trip-diary-f56de.firebaseio.com/posts.json';
var networkDataReceived = false;
fetch(url).then(function(res) {
return res.json();
}).then(function(data) {
networkDataReceived = true;
console.log('From Web', data);
var dataArray = [];
for(var key in data) {
dataArray.push(data[key]);
}
updateUI(dataArray);
});
if('indexedDB' in window) {
readAllData('posts').then(function(data) {
if(!networkDataReceived) {
console.log('From IndexedDB', data);
updateUI(data);
}
});
}
可以看到我將原本到cache裡尋找資源的部分,改成在indexedDB中呼叫readAllData() function,把indexedDB中的資料以一個陣列的方式回傳。最後透過updateUI() function將這些貼文資料更新到前端。
這裡還有一個地方需要修改,有的人可能會發現,當今天我在firebase又多增加了幾篇貼文後,OK!!在我的PWA中一切好像都是正常更新DER。
但是當我刪除firebase裡的某一則貼文,雖然前端顯示會不見,好像一切都是正常的。不過在indexedDB中還是會發現那則貼文是存在的。之所以這樣是因為我們是使用cache then network strategies,後來從網路fetch回來的data會overwrite前端的內容。
不過當用戶在離線狀態下,就會直接從indexedDB中來獲取貼文資訊,結果那責備我刪除的貼文又跑出來了啦QQ
這裡我的解決方法是在service worker中,每當從firebase fetch回貼文後都先「全部清除indexedDB」,之後再將最新的貼文儲存到indexedDB裡。
先在utility.js中實作清除indexedDB的方法:
function clearAllData(objectStore) {
return dbPromise.then(function(db) {
var tx = db.transaction(objectStore, 'readwrite');
var store = tx.objectStore(objectStore);
store.clear(); // 全部清除indexedDB中的資料
return tx.complete;
})
}
接著來看一下在sw.js中我更動的code:
if(event.request.url.indexOf(url) > -1) {
event.respondWith(
fetch(event.request).then(function(res) {
var clonedRes = res.clone();
clearAllData('posts').then(function() { // 先清除indexedDB
return clonedRes.json();
}).then(function(data) {
for(var key in data) {
writeData('posts', data[key]); // 再寫入新的data
}
});
return res;
})
);
} .... 以下省略 ....
實作到這裡,我的PWA中indexedDB的部分就告一段落了
總結一下針對PWA中的離線暫存,我這裡是將indexedDB應用到之前所學的「cache then network strategies」中,來暫存用戶經常會新增或刪除的dynamic data(json格式)。至於其他Application shell中的靜態資源或是其他用戶可能會訪問到的html、css、js和image檔案就交給Cache Storage來暫存。
Day16 結束!!